#ifndef COMMON_H
#define COMMON_H

#include <QMap>
#include <QPointF>
#include <QtMath>

enum GCODE
{
    G_00 = 0,
    G_01 = 10,
    G_02 = 20,
    G_03 = 30,
};

struct Block
{
    int gWord;
    QMap<QChar, qreal> items;
    void reset()
    {
        gWord = -1;
        items.clear();
    }
};

struct Setup
{
    double current_x;
    double current_y;
    void reset()
    {
        current_x = 0;
        current_y = 0;
    }
};

enum NodeType
{
    PK_LINE,
    PK_ARC,
};

struct BaseNode
{
    QPointF startPoint = QPointF(0, 0);
    QPointF endPoint;
    double length;
    virtual NodeType getKind() const = 0;
    virtual const QPointF& getEndPoint() const
    {
        return endPoint;
    }
    virtual double getLength() const
    {
        return length;
    }
};

struct LineNode : BaseNode
{
    LineNode(double endX, double endY)
    {
        endPoint.setX(endX);
        endPoint.setY(endY);
        length = hypot(endX, endY);
    }
    LineNode(QPointF end)
    {
        endPoint = end;
        length = hypot(end.x(), end.y());
    }

    NodeType getKind() const override
    {
        return PK_LINE;
    }
};

struct ArcNode : BaseNode
{
    double _radius;
    double swapAngle;
    QPointF _center; // with respect to the start, >0: CCW, <0: CW
    /**
     * @brief ArcNode
     * @param endX
     * @param endY
     * @param angle: in rad
     * @param centerX
     * @param centerY
     */
    ArcNode(double endX, double endY, double angle,
            double centerX, double centerY)
    {
        endPoint.setX(endX);
        endPoint.setY(endY);
        swapAngle = angle;
        _center.setX(centerX);
        _center.setY(centerY);
        _radius = hypot(endX - centerX, endY - centerY);
        length = _radius * angle;
    }
    ArcNode(QPointF end, double angle, QPointF center)
    {
        endPoint = end;
        swapAngle = angle;
        _center = center;
        _radius = hypot(end.x() - center.x(), end.y() - center.y());
        length = _radius * angle;
    }
    bool isCCW()
    {
        return (swapAngle > 0);
    }

    NodeType getKind() const override
    {
        return PK_ARC;
    }
};

struct PathGeometry
{
    double maxX = 0, minX = 0;
    double maxY = 0, minY = 0;
    void reset()
    {
        maxX = 0;
        minX = 0;
        maxY = 0;
        minY = 0;
    }
};

#endif // COMMON_H
